package com.pink.controller;

import com.pink.entity.vo.ResponseVo;
import com.pink.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestControllerAdvice
@RestController
public class AGlobalExceptionHandlerController implements ErrorController {

    // 处理404异常
    @RequestMapping("/error")
    public ResponseEntity<ResponseVo<Void>> handleError(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

        //打印路由信息+异常code
        log.error("url：{}，code：{}", request.getRequestURI(), statusCode);
        // 路由不存在时，返回404信息
        if (statusCode == HttpStatus.NOT_FOUND.value()) {
            return ResponseEntity
                    .status(HttpStatus.NOT_FOUND)
                    .body(ResponseVo.fail(404, "请求的资源不存在"));
        } else if (statusCode == HttpStatus.METHOD_NOT_ALLOWED.value()) {
            return ResponseEntity
                    .status(HttpStatus.METHOD_NOT_ALLOWED)
                    .body(ResponseVo.fail(405, "请求的方法不允许"));
        } else if (statusCode == HttpStatus.FORBIDDEN.value()) {
            return ResponseEntity
                    .status(HttpStatus.FORBIDDEN)
                    .body(ResponseVo.fail(403, "请求被拒绝"));
        } else if (statusCode == HttpStatus.UNAUTHORIZED.value()) {
            return ResponseEntity
                    .status(HttpStatus.UNAUTHORIZED)
                    .body(ResponseVo.fail(401, "未授权"));
        } else if (statusCode == HttpStatus.REQUEST_TIMEOUT.value()) {
            return ResponseEntity
                    .status(HttpStatus.REQUEST_TIMEOUT)
                    .body(ResponseVo.fail(408, "请求超时"));
        } else if (statusCode == HttpStatus.TOO_MANY_REQUESTS.value()) {
            return ResponseEntity
                    .status(HttpStatus.TOO_MANY_REQUESTS)
                    .body(ResponseVo.fail(429, "请求过多"));
        } else if (statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
            return ResponseEntity
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ResponseVo.fail(500, "系统错误，请联系管理员"));
        } else if (statusCode == HttpStatus.NOT_IMPLEMENTED.value()) {
            return ResponseEntity
                    .status(HttpStatus.NOT_IMPLEMENTED)
                    .body(ResponseVo.fail(501, "服务器不支持当前请求的功能"));
        } else if (statusCode == HttpStatus.SERVICE_UNAVAILABLE.value()) {
            return ResponseEntity
                    .status(HttpStatus.SERVICE_UNAVAILABLE)
                    .body(ResponseVo.fail(503, "服务器暂时不可用"));
        } else if (statusCode == HttpStatus.METHOD_FAILURE.value()) {
            return ResponseEntity
                    .status(HttpStatus.METHOD_FAILURE)
                    .body(ResponseVo.fail(500, "服务器内部错误"));
        } else if (statusCode == HttpStatus.MOVED_PERMANENTLY.value()) {
            return ResponseEntity
                    .status(HttpStatus.MOVED_PERMANENTLY)
                    .body(ResponseVo.fail(301, "资源已永久移动"));
        } else if (statusCode == HttpStatus.MOVED_TEMPORARILY.value()) {
            return ResponseEntity
                    .status(HttpStatus.MOVED_TEMPORARILY)
                    .body(ResponseVo.fail(302, "资源已临时移动"));
        } else if (statusCode == HttpStatus.NOT_MODIFIED.value()) {
            return ResponseEntity
                    .status(HttpStatus.NOT_MODIFIED)
                    .body(ResponseVo.fail(304, "资源未修改"));
        } else if (statusCode == HttpStatus.CONFLICT.value()) {
            return ResponseEntity
                    .status(HttpStatus.CONFLICT)
                    .body(ResponseVo.fail(409, "请求冲突"));
        } else if (statusCode == HttpStatus.GONE.value()) {
            return ResponseEntity
                    .status(HttpStatus.GONE)
                    .body(ResponseVo.fail(410, "资源已删除"));
        } else if (statusCode == HttpStatus.PRECONDITION_FAILED.value()) {
            return ResponseEntity
                    .status(HttpStatus.PRECONDITION_FAILED)
                    .body(ResponseVo.fail(412, "前提条件失败"));
        } else if (statusCode == HttpStatus.REQUEST_ENTITY_TOO_LARGE.value()) {
            return ResponseEntity
                    .status(HttpStatus.REQUEST_ENTITY_TOO_LARGE)
                    .body(ResponseVo.fail(413, "请求实体太大"));
        } else if (statusCode == HttpStatus.REQUEST_URI_TOO_LONG.value()) {
            return ResponseEntity
                    .status(HttpStatus.REQUEST_URI_TOO_LONG)
                    .body(ResponseVo.fail(414, "请求的URI太长"));
        } else if (statusCode == HttpStatus.UNSUPPORTED_MEDIA_TYPE.value()) {
            return ResponseEntity
                    .status(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
                    .body(ResponseVo.fail(415, "不支持的媒体类型"));
        } else if (statusCode == HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE.value()) {
            return ResponseEntity
                    .status(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE)
                    .body(ResponseVo.fail(431, "请求头字段太大"));
        } else if (statusCode == HttpStatus.TOO_EARLY.value()) {
            return ResponseEntity
                    .status(HttpStatus.TOO_EARLY)
                    .body(ResponseVo.fail(410, "资源已删除"));
        }
        // 其他异常时，返回500信息
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ResponseVo.fail(500, "系统错误，请联系管理员"));
    }

    // 处理@RequestParam/@PathVariable参数校验异常（包含@NotBlank）
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<ResponseVo<Void>> handleConstraintViolation(
            ConstraintViolationException ex) {
        String errorMsg = ex.getConstraintViolations().stream()
                .map(violation -> {
                    String path = violation.getPropertyPath().toString();
                    String field = path.substring(path.lastIndexOf('.') + 1);
                    return String.format("%s:%s", field,violation.getMessage());
                })
                .collect(Collectors.joining("; "));
        log.error("参数校验异常: {}", errorMsg);
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(ResponseVo.fail(400, "参数不符合要求"));
    }

    // 专门处理业务异常
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ResponseVo<Void>> handleBusinessException(BusinessException e) {
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(ResponseVo.fail(
                        e.getCode(),
                        e.getMessage()
                ));
    }

    // 处理其他异常
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ResponseVo<Void>> handleException(Exception e) {
        log.error("系统异常", e);
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ResponseVo.fail(500, "系统错误，请联系管理员"));
    }
}
